MySQL Replication主从复制原理及拓扑结构

复制解决的问题

1.备份容灾

不同备库分布在不用的地理位置,物理隔绝,可以用来备份数据和容灾

2.负载均衡

复制可以将多个读操作分布到不用的备库服务器,实现对读密集型应用的优化

3.高可用性能和故障切换

复制能避免MySQL单点故障,某个节点发生宕机,可以快速记性故障切换,提高系统高可用性

4.MySQL升级测试

这种做法较普遍,使用一个更高版本的MySQL作为备库,保证在升级全部实例前,查询能正常在其他备库上进行

复制如何工作

复制有三个步骤:

1.在主库上把更改记录到二进制日志(Binary Log)中(这些记录被称为二进制日志事件)

2.备库将主库上的日志复制到自己的中继日志(Relay Log)中

3.备库读取中继日志中的事件,将其重放到备库数据库

下图更详细描述复制的细节:

复制原理

第一步中,每次准备提交事务完成数据更新前,主库将数据更新的事件记录到二进制日志中,完了才会一起提交事务,所以不用担心数据更新了,但是二进制日志更新却失败的情况出现

下一步,备库会启动一个I/O线程和主库建立连接,主库上启动一个特殊的二进制转储(binlog dump)线程读取二进制日志中的事件,备库I/O线程会将接收到的事件记录到中继日志中

最后一步,备库的SQL线程重中继日志中读取事件并在备库上执行,从而实现数据更新

复制的原理

基于语句的复制

在MySQL5.0及之前的版本只支持基于语句的复制(也称为逻辑复制)。这种复制模式下,主库会记录数据更改的语句,备库将这些更改语句再执行一遍完成复制,这样做有好处也有坏处

好处:

  • 实现简单
  • 节省带宽空间,一条更新好几兆数据的语句在一个二进制日志里可能只有几十个字节

坏处:

  • 存在无法被正确复制的SQL,比如获取当前时间戳、使用CURRENT_USER()函数的语句
  • 更新必须串行,这需要更多的锁

基于行的复制

MySQL5.1开始支持基于行的复制,这种方式会将实际数据记录在二进制日志中

好处:

  • 可以正确复制每一行,对于一些需要从大表查询结果汇总到小表的更新,如果更新行数很少,效率相对于基于语句的复制更高效

坏处:

  • 对于更新行数很大的更新,会使二进制日志事件非常庞大,给主库记录日志和备库复制增加额外的负载

复制拓扑结构

可以在任意主库和备库之间建立复制,唯一的限制是每个备库只能有一个主库,这样一来,复制拓扑结构就非常多了,不同的拓扑结构只须遵循以下原则:

  • 一个备库只能有一个主库
  • 每个备库必须有一个唯一的服务器ID
  • 一个主库可以有多个备库
  • 一个备库可以把其主库上的数据变化传递到其他备库,需要log_slave_updates选项设置为1,即允许备库将其重放的事件也记录到自身的二进制日志中

复制拓扑结构很多,下面介绍几种常见的

一主多备

一主多备

最简单的拓扑结构,再有少量写大量读的时候,可以通过读写分离减小负载。还有,可以将备库放到不同地理位置的机房,做数据备份容灾

主动-主动模式下的主-主复制

双主复制-主动

主-主复制(也叫双主复制或双向复制),每一个都被配置成对方的主库和备库。该拓扑可能的应用场景是两个处于不同地理位置的办公室,并且都需要可写的数据拷贝。这种配置最大的问题是如何解决冲突,两个可写的互主服务器导致的问题非常多,通常发生在两天服务器同时修改同一行记录,或者同时向包含auto_increment列的表里插入数据,会造成两边数据不一致

主动-被动模式下的主-主复制

双主复制-被动

和上一种主要区别在于其中一台服务器是只读的被动服务器。这种方式使得切换主动和被动服务器非常方便,因为服务器配置是对称的。这使得故障转移和故障恢复很容易。它也可以让你在不关闭服务器的情况下维护、优化表。

级联复制

级联复制

直接从属主库的备库太多时,连接到主库的I/O线程比较多,增大主库压力,它的缺点是中间层出现错误,会影响到多个服务器,中间层层次越多,故障处理越复杂

参考

[1] 《高性能MySQL》